/**
 * Generali Solutions d'assurances - Tous droits réservés &copy; 2007 - 2010
 */
package fr.generali.accueilclient.client.assembler.input;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import fr.generali.accueilclient.client.om.IClientAssociation;
import fr.generali.accueilclient.client.om.IClientAutre;
import fr.generali.accueilclient.client.om.IClientEntreprise;
import fr.generali.accueilclient.client.om.IPersonne;
import fr.generali.accueilclient.client.om.IPersonneMorale;
import fr.generali.accueilclient.client.om.IPersonnePhysique;
import fr.generali.accueilclient.client.om.NaturePersonne;
import fr.generali.refservcommuns.rce.demat.communcontact.dossiercontact.DtoDossierMajDossierContact;
import fr.generali.refservcommuns.rce.demat.communcontact.dossiercontact.DtoListeDossierMajAdresse;
import fr.generali.refservcommuns.rce.demat.communcontact.dossiercontact.DtoListeDossierMajCourriel;
import fr.generali.refservcommuns.rce.demat.communcontact.dossiercontact.DtoListeDossierMajPageWeb;
import fr.generali.refservcommuns.rce.demat.communcontact.dossiercontact.DtoListeDossierMajTelephone;
import fr.generali.refservcommuns.rce.demat.communmajmarketing.majmarketing.DtoMajProfilMarketing;
import fr.generali.refservcommuns.rce.demat.creationpersonne.creationpersonneservice.CreerPersonne;
import fr.generali.refservcommuns.rce.demat.creationpersonne.dtocreerpersonne.DtoDossierP12;
import fr.generali.refservcommuns.rce.demat.creationpersonne.dtocreerpersonne.DtoListeDossierP12;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoPersonneMorale;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoPersonnePhysique;

/**
 * @author selrhazala
 */
@Component("personneToCreerPersonneConverter")
public class PersonneToCreerPersonneConverter implements Converter<IPersonne, CreerPersonne> {

    /**
     * Code user
     */
    private static final String CODE_USER = "BC";
    
    /**
     * Code personnel
     */
    private static final String PROFESSIONNEL = "PRO";
    
    /**
     * Code personnel
     */
    private static final String PERSONNEL = "PER";
    
    /**
     * Assembler pour une personne physique
     */
    @Autowired
    @Qualifier("personnePhysiqueToDtoPersonnePhysiqueConverter")
    private Converter<IPersonnePhysique, DtoPersonnePhysique> personnePhysiqueToDtoPersonnePhysiqueConverter;
    
    /**
     * Assembler pour une personne morale
     */
    @Autowired
    @Qualifier("personneMoraleToDtoPersonneMoraleConverter")
    private Converter<IPersonneMorale, DtoPersonneMorale> personneMoraleToDtoPersonneMoraleConverter;
    
    /**
     * Assembler pour le pro côté personne morale
     */
    @Autowired
    @Qualifier("personnePhysiqueToDtoPersonneMoraleConverter")
    private Converter<IPersonnePhysique, DtoPersonneMorale> personnePhysiqueToDtoPersonneMoraleConverter;
    
    /**
     * Assembler pour dossier de contact de personne toutes natures
     */
    @Autowired
    @Qualifier("personneToDtoDossierMajDossierContactConverter")
    private Converter<IPersonne, DtoDossierMajDossierContact> personneToDtoDossierMajDossierContactConverter;
    
    /**
     * {@inheritDoc}
     */
    public CreerPersonne convert(IPersonne input) {
        CreerPersonne creerPersonne = null;
        if (input != null) {
            creerPersonne = new CreerPersonne();
            DtoDossierP12 dtoDossierP12 = new DtoDossierP12();

            // init date du jour
            XMLGregorianCalendar dateDuJour = null;
            try {
                GregorianCalendar gCalendar1 = new GregorianCalendar();
                gCalendar1.setTime(new Date());
                dateDuJour = DatatypeFactory.newInstance().newXMLGregorianCalendar(gCalendar1);
            } catch (DatatypeConfigurationException e) {
                e.getMessage();
            }
            
            DtoDossierMajDossierContact dossierContact = personneToDtoDossierMajDossierContactConverter.convert(input);
            
            dtoDossierP12.setCodeUser(CODE_USER);
            dtoDossierP12.setProfilMarketing(buildProfilMarketing(input, dateDuJour));
            
            if (!NaturePersonne.PROFESSIONNEL.equals(input.getNaturePersonne())) {
                dtoDossierP12.setDossierContact(dossierContact);
            }
            
            if (input.isPersonnePhysique()) {
                IPersonnePhysique personnePhysique = IPersonnePhysique.class.cast(input);
                if (NaturePersonne.PROFESSIONNEL.equals(personnePhysique.getNaturePersonne())) {
                    dtoDossierP12.setPersonneMorale(
                                    personnePhysiqueToDtoPersonneMoraleConverter.convert(personnePhysique));
                    
                    dtoDossierP12.setDossierContact(majDossierContactPriveeForPro(dossierContact));
                    dtoDossierP12.setDossierContactSpherePro(majDossierContactProForPro(
                                    personneToDtoDossierMajDossierContactConverter.convert(input)));
                }
                dtoDossierP12.setPersonnePhysique(
                                personnePhysiqueToDtoPersonnePhysiqueConverter.convert(personnePhysique));
            } else {
                IPersonneMorale personneMorale = IPersonneMorale.class.cast(input);
                dtoDossierP12.setPersonneMorale(personneMoraleToDtoPersonneMoraleConverter.convert(personneMorale));
            }

            List<DtoDossierP12> listeDossierP12 = new ArrayList<DtoDossierP12>();
            listeDossierP12.add(dtoDossierP12);
            if (creerPersonne.getDtoListeDossierP12() == null) {
                creerPersonne.setDtoListeDossierP12(new DtoListeDossierP12());
            }
            creerPersonne.getDtoListeDossierP12().getDossierP12().addAll(listeDossierP12);
        }

        return creerPersonne;
    }
    
    /**
     * @param dossierContact le dossier de contact
     * @return DtoDossierMajDossierContact le dossier de contact mis à jour pour un client pro
     */
    private DtoDossierMajDossierContact majDossierContactProForPro(DtoDossierMajDossierContact dossierContact) {
        DtoDossierMajDossierContact dossierContactPro = new DtoDossierMajDossierContact();
        
        // RG : la personne physique d'un client pro ne peut pas avoir d'adresse PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getAdresse())) {
            List<DtoListeDossierMajAdresse> listeAdressePro = new ArrayList<DtoListeDossierMajAdresse>();
            for (int i = 0; i < dossierContact.getAdresse().size(); i++) {
                DtoListeDossierMajAdresse dossier = dossierContact.getAdresse().get(i);
                if (dossier != null 
                                && dossier.getDtoAdressePostale() != null) {
                    dossier.getDtoAdressePostale().setCodeTypeModeContact(PROFESSIONNEL);
                    listeAdressePro.add(dossier);
                }
            }
            dossierContactPro.getAdresse().addAll(listeAdressePro);
        }
        
        // RG : la personne physique d'un client pro ne peut pas avoir de téléphone PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getTelephone())) {
            List<DtoListeDossierMajTelephone> listeTelephonePro = new ArrayList<DtoListeDossierMajTelephone>();
            for (int i = 0; i < dossierContact.getTelephone().size(); i++) {
                DtoListeDossierMajTelephone dossier = dossierContact.getTelephone().get(i);
                if (dossier != null 
                                && dossier.getDtoTelephone() != null
                                && dossier.getDtoTelephone().getCodeTypeModeContact().equals(PROFESSIONNEL)) {
                    listeTelephonePro.add(dossier);
                }
            }
            dossierContactPro.getTelephone().addAll(listeTelephonePro);
        }
        
        // RG : la personne physique d'un client pro ne peut pas avoir d'email PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getCourriel())) {
            List<DtoListeDossierMajCourriel> listeCourrielPro = new ArrayList<DtoListeDossierMajCourriel>();
            for (int i = 0; i < dossierContact.getCourriel().size(); i++) {
                DtoListeDossierMajCourriel dossier = dossierContact.getCourriel().get(i);
                if (dossier != null 
                                && dossier.getDtoCourriel() != null
                                && dossier.getDtoCourriel().getCodeTypeModeContact().equals(PROFESSIONNEL)) {
                    listeCourrielPro.add(dossier);
                }
            }
            dossierContactPro.getCourriel().addAll(listeCourrielPro);
        }
        
        // RG : la personne physique d'un client pro ne peut pas avoir de site internet PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getPageWeb())) {
            List<DtoListeDossierMajPageWeb> listePageWebPro = new ArrayList<DtoListeDossierMajPageWeb>();
            for (int i = 0; i < dossierContact.getPageWeb().size(); i++) {
                DtoListeDossierMajPageWeb dossier = dossierContact.getPageWeb().get(i);
                if (dossier != null 
                                && dossier.getDtoPageWeb() != null
                                && dossier.getDtoPageWeb().getCodeTypeModeContact().equals(PROFESSIONNEL)) {
                    listePageWebPro.add(dossier);
                }
            }
            dossierContactPro.getPageWeb().addAll(listePageWebPro);
        }
        
        dossierContactPro.getStopCom().addAll(dossierContact.getStopCom());
        dossierContactPro.setCodecanalPrefere(dossierContact.getCodecanalPrefere());
        dossierContactPro.setDemarchage(dossierContact.getDemarchage());
        
        return dossierContactPro;
    }
    
    /**
     * @param dossierContact le dossier de contact
     * @return DtoDossierMajDossierContact le dossier de contact mis à jour pour un client pro
     */
    private DtoDossierMajDossierContact majDossierContactPriveeForPro(DtoDossierMajDossierContact dossierContact) {
        DtoDossierMajDossierContact dossierContactPro = new DtoDossierMajDossierContact();
        
        // RG : la personne physique d'un client pro ne peut pas avoir d'adresse PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getAdresse())) {
            List<DtoListeDossierMajAdresse> listeAdressePro = new ArrayList<DtoListeDossierMajAdresse>();
            for (int i = 0; i < dossierContact.getAdresse().size(); i++) {
                DtoListeDossierMajAdresse dossier = dossierContact.getAdresse().get(i);
                if (dossier != null 
                                && dossier.getDtoAdressePostale() != null) {
                    dossier.getDtoAdressePostale().setCodeTypeModeContact(PERSONNEL);
                    listeAdressePro.add(dossier);
                }
            }
            dossierContactPro.getAdresse().addAll(listeAdressePro);
        }
        
        // RG : la personne physique d'un client pro ne peut pas avoir de téléphone PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getTelephone())) {
            List<DtoListeDossierMajTelephone> listeTelephonePro = new ArrayList<DtoListeDossierMajTelephone>();
            for (int i = 0; i < dossierContact.getTelephone().size(); i++) {
                DtoListeDossierMajTelephone dossier = dossierContact.getTelephone().get(i);
                if (dossier != null 
                                && dossier.getDtoTelephone() != null
                                && !dossier.getDtoTelephone().getCodeTypeModeContact().equals(PROFESSIONNEL)) {
                    listeTelephonePro.add(dossier);
                }
            }
            dossierContactPro.getTelephone().addAll(listeTelephonePro);
        }
        
        // RG : la personne physique d'un client pro ne peut pas avoir d'email PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getCourriel())) {
            List<DtoListeDossierMajCourriel> listeCourrielPro = new ArrayList<DtoListeDossierMajCourriel>();
            for (int i = 0; i < dossierContact.getCourriel().size(); i++) {
                DtoListeDossierMajCourriel dossier = dossierContact.getCourriel().get(i);
                if (dossier != null 
                                && dossier.getDtoCourriel() != null
                                && !dossier.getDtoCourriel().getCodeTypeModeContact().equals(PROFESSIONNEL)) {
                    listeCourrielPro.add(dossier);
                }
            }
            dossierContactPro.getCourriel().addAll(listeCourrielPro);
        }
        
        // RG : la personne physique d'un client pro ne peut pas avoir de site internet PRO
        if (CollectionUtils.isNotEmpty(dossierContact.getPageWeb())) {
            List<DtoListeDossierMajPageWeb> listePageWebPro = new ArrayList<DtoListeDossierMajPageWeb>();
            for (int i = 0; i < dossierContact.getPageWeb().size(); i++) {
                DtoListeDossierMajPageWeb dossier = dossierContact.getPageWeb().get(i);
                if (dossier != null 
                                && dossier.getDtoPageWeb() != null
                                && !dossier.getDtoPageWeb().getCodeTypeModeContact().equals(PROFESSIONNEL)) {
                    listePageWebPro.add(dossier);
                }
            }
            dossierContactPro.getPageWeb().addAll(listePageWebPro);
        }
        
        if (CollectionUtils.isNotEmpty(dossierContact.getStopCom())) {
            dossierContact.getStopCom().get(0).setCodeTypeModeContact(PERSONNEL);
        }
        
        dossierContactPro.getStopCom().addAll(dossierContact.getStopCom());
        dossierContactPro.setCodecanalPrefere(dossierContact.getCodecanalPrefere());
        dossierContactPro.setDemarchage(dossierContact.getDemarchage());
        
        return dossierContactPro;
    }
    
    /**
     * @param client le client
     * @param dateDuJour la date du jour
     * @return DtoMajProfilMarketing le profil marketing du client à créer
     */
    private DtoMajProfilMarketing buildProfilMarketing(IPersonne client,
                                                      XMLGregorianCalendar dateDuJour) {
        
        String nbSites = StringUtils.EMPTY;
        switch (client.getNaturePersonne()) {
            case PARTICULIER:
                nbSites = client.getNbResidences();
                break;
            case PROFESSIONNEL:
                nbSites = client.getNbResidences();
                break;
            case ASSOCIATION:
                nbSites = IClientAssociation.class.cast(client).getNbSites();
                break;
            case COLLECTIVITE:
                nbSites = client.getNbResidences();
                break;
            case COPROPRIETE:
                nbSites = client.getNbResidences();
                break;
            case ENTREPRISE:
                nbSites = IClientEntreprise.class.cast(client).getNbSites();
                break;
            default:
                nbSites = IClientAutre.class.cast(client).getNbSites();
                break;
        }
        
        DtoMajProfilMarketing dtoMajProfilMarketing = new DtoMajProfilMarketing();
        if (StringUtils.isNotEmpty(nbSites)) {
            dtoMajProfilMarketing.setNombreBiensImmobiliers(BigInteger.valueOf(Long.parseLong(nbSites)));
        }
        dtoMajProfilMarketing.setDateMiseAJourNombreBienImmobiliers(dateDuJour);
        if (StringUtils.isNotEmpty(client.getNbVehicules())) {
            dtoMajProfilMarketing.setNombreVehicules(BigInteger.valueOf(Long.parseLong(client.getNbVehicules())));
        }
        dtoMajProfilMarketing.setDateMiseaJourNombreVehicules(dateDuJour);
        dtoMajProfilMarketing.setPollicitable(client.isPollicitable());
        dtoMajProfilMarketing.setAssurableEnSante(client.isAssurableEnSante());
        
        return dtoMajProfilMarketing;
    }
    
}
